package org.tio.webpack.http;

import java.util.HashMap;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.http.common.MimeType;
import org.tio.http.common.RequestLine;
import org.tio.http.server.intf.HttpServerInterceptor;
import org.tio.utils.lock.MapWithLock;
import org.tio.webpack.cache.CacheVo;
import org.tio.webpack.compress.ResCompressor;
import org.tio.webpack.compress.ResCompressorFactory;

/**
 * @author tanyaowu 
 * 2017年11月17日 下午3:09:27
 */
public class TioWebpackHttpServerInterceptor implements HttpServerInterceptor {
	private static Logger log = LoggerFactory.getLogger(TioWebpackHttpServerInterceptor.class);

	MapWithLock<String, CacheVo> cacheMap = new MapWithLock<>(new HashMap<>());

	/**
	 * 
	 * @author tanyaowu
	 */
	public TioWebpackHttpServerInterceptor() {
	}

	/**
	 * TODO 注意：本处的实现并未过多考虑性能
	 * @param request
	 * @param requestLine
	 * @param response
	 * @throws Exception
	 * @author tanyaowu
	 */
	@Override
	public void doAfterHandler(HttpRequest request, RequestLine requestLine, HttpResponse response) throws Exception {
		if (response == null) {
			return;
		}
		String contentType = response.getContentType();

		if (contentType == null) {
			return;
		}
		
		MimeType mimeType = MimeType.fromType(contentType);
		if (mimeType != null) {
			String extension = mimeType.getExtension();
			
			if (ResCompressorFactory.isNeedCompress(extension)) {
				ResCompressor resCompressor = ResCompressorFactory.get(extension);
				if (resCompressor != null) {
					String path = requestLine.getPath();
					String initStr = new String(response.getBody(), request.getCharset());
					String body = null;
					CacheVo cacheVo = cacheMap.get(path);
					if (cacheVo != null) {
						if (Objects.equals(initStr, cacheVo.getInitData())) {
							body = cacheVo.getCompressedData();
							response.addHeader("tio-webpack-used-cache", "1");
						}
					}
					if (body == null) {
						String compressedStr = resCompressor.compress(path, initStr);
						cacheVo = new CacheVo();
						cacheVo.setInitData(initStr);
						cacheVo.setCompressedData(compressedStr);
						cacheMap.put(path, cacheVo);

						body = compressedStr;
					}

					response.setBody(body.getBytes(request.getCharset()), request);
				}
			}
		}
	}

	/** 
	 * @param packet
	 * @param requestLine
	 * @param httpResponseFromCache
	 * @return
	 * @throws Exception
	 * @author tanyaowu
	 */
	@Override
	public HttpResponse doBeforeHandler(HttpRequest request, RequestLine requestLine, HttpResponse responseFromCache) throws Exception {
		return null;
	}

	/**
	 * @param args
	 * @author tanyaowu
	 */
	public static void main(String[] args) {

	}
}
